<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <input type="file" id="input">
  <script>
    const CHUNK_SIZE = 0.5 * 1024 * 1024;

    // file 分割
    const slice = (file) => {
      const chunks = [];
      let cur = 0;
      while ((cur * CHUNK_SIZE) < file.size) {
        chunks.push({ index: cur, file: file.slice(cur * CHUNK_SIZE, ++cur * CHUNK_SIZE) });
      }
      
      return chunks;
    }

    // 通过 spark-md5 计算md5
    const appendToSpark = ({ file }) => {
      return new Promise((resolve) => {
        const reader = new FileReader()
        reader.readAsArrayBuffer(file)
        reader.onload = (e) => {
          resolve()
        }
      })
    }

    // 计算 md5
    const calculateHashIdle = (chunks) => {
      let count = 0;
      requestIdleCallback((deadline) => {
        console.log('11111111', deadline);
        if (count < chunks.length) {
          appendToSpark(chunks[count])
          count++
        }
      })
    }

    // 获取文件
    input.addEventListener('change', (file) => {
      const files = file.target.files
      if (files.length > 0) {
        for(let i = 0; i < files.length; i++) {
          const chunks = slice(files[i])
          // calculateHashIdle(chunks)
          allTaskListAdd(chunks)
          requestLimit()
        }
      }
    })

    // 模拟上传请求接口
    const request = ({ index, file }) => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (index !== 3) {
            resolve(index)
          } else {
            reject(index)
          }
        
        }, Math.random() * 1000)
      })
    }

    const taskList = [];
    const requestMap = new Map()

    // 将所有上传请求task放入到一个任务list中
    const allTaskListAdd = (chunks) => {
      chunks.forEach((item) => {
        taskList.push(() => {
          const { index } = item
          if (requestMap.size < 6) {
            requestMap.set(index, true)
          }
          return request(item)
        })
      })
    }

    // http上传请求限制
    const requestLimit = (chunks) => {
      while (requestMap.size < 6 && taskList.length > 0) {
        const task = taskList.shift()
        task().then(res => {
          requestMap.delete(res)
          if (taskList.length > 0) {
            requestLimit()
          }
        }, error => {
          // 重试
          console.log('------------', error);
        })
      }
    }
    
  </script>
</body>
</html>